package org.ala.tiktools.sharddb.mybatis.summary;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.ala.tiktools.mybatis.interfaces.IOrderBy;
import org.ala.tiktools.mybatis.pager.Pager;
import org.ala.tiktools.sharddb.exception.ShardDBRuntimeException;
import org.ala.tiktools.sharddb.mybatis.executor.ShardExecutor;
import org.ala.tiktools.sharddb.mybatis.interceptor.Shard;
import org.ala.tiktools.sharddb.mybatis.router.ShardInfo;
import org.ala.tiktools.sharddb.mybatis.summary.adapt.AdapeSummary;
import org.ala.tiktools.tools.CachingKVTools;

/**
 * 汇总执行器
 *
 * @author ala
 * @date 2025-02-21 12:59
 */
public class ShardSummaryHandler {


    /**
     *  适配汇总器
     */
    protected AdapeSummary adape = new AdapeSummary();


    /**
     *  执行汇总
     */
    public Object summary(Shard anno, Method method, Object[] args, Map<ShardInfo, ShardExecutor.Result> result) {
        //  如果Method本身搜void，不需要汇总
        Class<?> returnType = method.getReturnType();
        if (method.getReturnType().equals(Void.TYPE)) {
            return null;
        }
        //  如果只有1个分表，直接返回
        if (result.size() == 1) {
            return result.entrySet().iterator().next().getValue().getRes();
        }

        //  拿汇总器
        ISummary summary = adape.adape(anno, method);
        if (summary == null) {
            throw new ShardDBRuntimeException(String.format("没有配置结果汇总器，也无法适配 method:%s class:%s", method.getName(), method.getDeclaringClass().getSimpleName()));
        }

        //  拿排序器
        IOrderBy orderBy = getOrderBy(method, args);

        //  有排序时的汇总
        Object res = null;
        if (orderBy != null) {
            res = summaryWithOrderBy(summary, orderBy, result);
        }
        //  一般汇总
        if (res == null) {
            res = summaryWithoutOrderBy(summary, result);
        }

        //  如果无法执行汇总，直接抛异常
        if ( res== null) {
            throw new ShardDBRuntimeException(String.format("无法执行汇总，请确认@Shard注解是否配置了汇总器 method:%s class:%s", method.getName(), method.getDeclaringClass().getSimpleName()));
        }
        return res;
    }
    /**
     *  有排序时的汇总
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
	protected Object summaryWithOrderBy(ISummary summary, IOrderBy orderBy, Map<ShardInfo, ShardExecutor.Result> result) {
        if (summary instanceof IShardListOrderBySummary) {
            Map<ShardInfo, List> r =  result.entrySet().stream().collect(Collectors.toMap(e -> e.getKey(), e -> (List)e.getValue().getRes(), (o,n) -> n));
            return ((IShardListOrderBySummary) summary).summary(orderBy, r);
        } else if (summary instanceof IShardPagerOrderBySummary) {
            Map<ShardInfo, Pager> r =  result.entrySet().stream().collect(Collectors.toMap(e -> e.getKey(), e -> (Pager)e.getValue().getRes(), (o, n) -> n));
            return ((IShardPagerOrderBySummary) summary).summary(orderBy, r);
        } else if (summary instanceof IShardOrderBySummary) {
            Map<ShardInfo, Object> r = result.entrySet().stream().collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue().getRes(), (o, n) -> n));
            return ((IShardOrderBySummary) summary).summary(orderBy, r);
        } else if (summary instanceof ICustomSummary) {
        	return ((ICustomSummary) summary).summary(orderBy, result);
        }
        return null;
    }
    /**
     *  一般汇总
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    protected Object summaryWithoutOrderBy(ISummary summary, Map<ShardInfo, ShardExecutor.Result> result) {
        if (summary instanceof IShardListSummary) {
            Map<ShardInfo, List> r =  result.entrySet().stream().collect(Collectors.toMap(e -> e.getKey(), e -> (List)e.getValue().getRes(), (o,n) -> n));
            return ((IShardListSummary) summary).summary(r);
        } else if (summary instanceof IShardPagerSummary) {
            Map<ShardInfo, Pager> r =  result.entrySet().stream().collect(Collectors.toMap(e -> e.getKey(), e -> (Pager)e.getValue().getRes(), (o,n) -> n));
            return ((IShardPagerSummary) summary).summary(r);
        } else if (summary instanceof IShardSummary) {
            Map<ShardInfo, Object> r =  result.entrySet().stream().collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue().getRes(), (o,n) -> n));
            return ((IShardSummary) summary).summary(r);
        } else if (summary instanceof ICustomSummary) {
        	return ((ICustomSummary) summary).summary(result);
        }
        return null;
    }


    /**
     *  从method中拿IOrderBy
     */
    protected IOrderBy getOrderBy(Method method, Object[] args) {
        Integer idx = orderByMapper.get(method);
        if (idx == null || idx < 0) {return null;}

        return (IOrderBy) args[idx];
    }
    /**
     *  method参数中IOrderBy的下标
     */
    protected CachingKVTools<Method, Integer> orderByMapper = new CachingKVTools<>(-1, m -> {
        for (int i = 0; i < m.getParameters().length; i++) {
            if (IOrderBy.class.isAssignableFrom(m.getParameters()[i].getType())) {
                return i;
            }
        }
        return null;
    });
}
